#region license
/*
 * Copyright (C) 2007 CchenSoft.com
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License 2.1 or later, as
 * published by the Free Software Foundation. See the included License.txt
 * or http://www.gnu.org/copyleft/lesser.html for details.
 * 
 * Author: Billy Zhang
 */
#endregion

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.Web;
using CchenSoft.Portal.Util;
using CchenSoft.Portal.Service;
using CchenSoft.Portal.Model;
using CchenSoft.Portal.Registry;
using CchenSoft.Portal.Spi.Registry;
using CchenSoft.Portal.Spi.Service;

namespace CchenSoft.Portal.Web.UI
{
    public class PortletPage : System.Web.UI.Page
    {
        protected PortletContext portletContext;
        protected PortalURL portalURL;
        protected PortletEntry portlet;
        protected int instanceId;
        protected string portletName;
        protected PortletInstance instance;
        protected PortletPreferences preferences;
        protected string dataInput;
        protected IExportService exportService;
        protected IList<Producer> producers = new List<Producer>();

        protected virtual string GetExportService()
        {
            return Request.Headers["portal-exportservice"];
        }

        protected virtual string GetPortalUrl()
        {
            return Request.Headers["portal-url"];
        }

        protected virtual int GetInstanceId()
        {
            return ConvertUtil.ToInt32(Request.Headers["portlet-instanceId"]);
        }

        protected virtual string GetPortletName()
        {
            return Request.Headers["portlet-name"];
        }

        protected virtual IList<Producer> Producers
        {
            get { return producers; }
        }

        protected override void OnLoad(EventArgs e)
        {
            string esTypeString = GetExportService();
            if (!string.IsNullOrEmpty(esTypeString))
            {
                Type esType = Type.GetType(esTypeString);
                exportService = (IExportService)Activator.CreateInstance(esType);
            }
            portalURL = PortalURL.FromXml(GetPortalUrl());
            instanceId = GetInstanceId();

            if (exportService != null)
                instance = exportService.LoadPortletInstance(instanceId);

            string prefs = (instance != null) ? instance.Preferences : "";
            preferences = PortletPreferences.FromXml(prefs);

            portletName = GetPortletName();
            if (exportService != null)
            {
                if (instance != null)
                    portlet = exportService.GetPortlet(instance.PortletId);
                else if (!string.IsNullOrEmpty(portletName))
                    portlet = exportService.GetPortlet(portletName);
            }

            dataInput = Request.Headers["portlet-dataInput"];

            string str = Request.Headers["producers"];
            if (!string.IsNullOrEmpty(str))
            {
                string[] arr = str.Split(';');
                foreach (string s in arr)
                {
                    string[] arr2 = s.Split(',');
                    if (arr2.Length > 1)
                    {
                        int instId = ConvertUtil.ToInt32(arr2[0]);
                        if (instId > 0)
                        {
                            producers.Add(new Producer(instId, arr2[1]));
                        }
                    }
                }
            }

            portletContext = PortletContext.Current;
            base.OnLoad(e);
        }

        protected void OutputData(string data)
        {
            Response.AddHeader("portlet-dataOutput", data);
        }

        protected bool IsOwner()
        {
            return instance != null && portletContext.User != null && instance.UserId == portletContext.User.UserId;
        }

        protected bool IsAdmin()
        {
            return portletContext.User != null && portletContext.User.IsAdmin;
        }

        public int InstanceId
        {
            get { return instanceId; }
        }

        public string PortletName
        {
            get { return portletName; }
        }

        public PortletEntry Portlet
        {
            get { return portlet; }
        }

        public IExportService ExportService
        {
            get { return exportService; }
        }

        public PortalURL PortalURL
        {
            get { return portalURL; }
        }

        protected void UpdatePreferences(PortletPreferences preferences)
        {
            exportService.UpdatePreferences(instanceId, preferences.ToXml());
        }

        protected void RemoveParam(string name)
        {
            portalURL.RemoveParam("_" + instanceId + "_" + name);
        }

        public string BuildPortalUrl(string oldUrl, string targetPortlet, string targetQuery)
        {
            string oldPath = "";
            NameValueCollection oldParams = new NameValueCollection();

            int n = oldUrl.IndexOf("?");
            if (n > -1)
            {
                oldPath = oldUrl.Substring(0, n);
                oldParams = HttpUtility.ParseQueryString(oldUrl.Substring(n + 1));
            }
            else
            {
                oldPath = oldUrl;
            }

            // add hyperlink parameters.
            IDictionary<string, string> newParams = new Dictionary<string, string>();
            foreach (string name in oldParams)
            {
                newParams.Add("_" + instanceId + "_" + name, oldParams[name]);
            }

            StringBuilder sb = new StringBuilder();

            // add action.            
            sb.Append(portalURL.RequestPath);
            bool hasParam = false;
            if (!string.IsNullOrEmpty(oldPath))
            {
                sb.AppendFormat("?_{0}_action={1}", instanceId, oldPath);
                hasParam = true;
            }
            newParams.Remove("_" + instanceId + "_action");

            foreach (string name in newParams.Keys)
            {
                sb.Append((hasParam) ? "&" : "?");
                sb.AppendFormat("{0}={1}", name, newParams[name]);
                hasParam = true;
            }

            // add target portlet query
            if (!string.IsNullOrEmpty(targetPortlet) && !string.IsNullOrEmpty(targetQuery))
            {
                NameValueCollection targetParams = null;
                string targetPath = "";

                int pos = targetQuery.IndexOf("?");
                if (pos > -1)
                {
                    targetPath = targetQuery.Substring(0, pos);
                    targetParams = HttpUtility.ParseQueryString(targetQuery.Substring(pos + 1));
                }
                else
                {
                    targetPath = "";
                    targetParams = HttpUtility.ParseQueryString(targetQuery);
                }

                if (!string.IsNullOrEmpty(targetPath))
                {
                    sb.Append((hasParam) ? "&" : "?");
                    sb.AppendFormat("_{0}_action={1}", targetPortlet, targetPath);
                    hasParam = true;
                }

                foreach (string name in targetParams.Keys)
                {
                    sb.Append((hasParam) ? "&" : "?");
                    sb.AppendFormat("_{0}_{1}={2}", targetPortlet, name, targetParams[name]);
                    hasParam = true;
                }
            }

            return sb.ToString();
        }

        protected override void OnError(EventArgs e)
        {
            Exception ex = Server.GetLastError();
            if (ex is SecurityException)
            {
                Response.Write(ex.Message);
                Logger.Warn(ex.Message, this.GetType());
            }
            else
            {
                Response.Write(ex.Message);
                Logger.Error(ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine + ex.Source, this.GetType());
            }
            Response.End();
        }
    }
}
